package com.hxzy.controller;

import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import com.hxzy.common.dto.ExistsDTO;
import com.hxzy.common.enums.AckCode;
import com.hxzy.common.exception.HospitalException;
import com.hxzy.common.web.controller.BaseController;
import com.hxzy.service.ExistsService;
import org.springframework.beans.factory.annotation.Autowired;

import java.lang.annotation.Annotation;
import java.lang.reflect.Field;

/**
 * 判断值是否存在的通用控制器
 *
 * @author tonneyyy
 */
public class ExistsValueController extends BaseController {

    @Autowired
    private ExistsService existsService;

    /**
     * 验证商家数据唯一的
     * @param entity   实体类(mybatis-plus声明过)
     * @param shopColumnName   商家列数据库字段
     * @param columnName       验证数据库某个列名
     * @param columnValue      验证数据库某个列的值
     */
    protected void shopValidateExistsValue(Object entity,String shopColumnName,String columnName,String columnValue) throws IllegalAccessException {
        ExistsDTO brandNameDto=new ExistsDTO();

        //反射
        Class  cls=entity.getClass();

        String className= cls.getSimpleName();

        //获取类上的注解
        Annotation tableName = cls.getDeclaredAnnotation(TableName.class);
        if(tableName==null){
            throw new HospitalException(StrUtil.format("{}实体类上面注解要有@TableName注解", className));
        }
        String tableNameValue=((TableName)tableName).value();


        boolean hasTableId=false;
        //先要获取所有的字段，再判断这个字段上是否有 这个 TableId
        Field[] declaredFields = cls.getDeclaredFields();
        for(Field fi:  declaredFields){
            TableId tableIdAnnon = fi.getDeclaredAnnotation(TableId.class);
            if(tableIdAnnon!=null){
                hasTableId=true;
                String tableIdValue=tableIdAnnon.value();
                //如果注解没有 value 值
                if(StrUtil.isBlank(tableIdValue)){
                    //得到字段名
                    String fieldName= fi.getName();
                    tableIdValue= camelToUnderline( fieldName);
                }

                //开启强制访问私有变量
                fi.setAccessible(true);
                Object fiValue = fi.get(entity);
                if(fiValue!=null){
                    //主键列
                    brandNameDto.setPkName(tableIdValue);
                    brandNameDto.setPkValue( fiValue.toString());
                }

                break;
            }
        }

        // 如果实体类没有 @TableId主键,提示错误
        if(!hasTableId){
            throw new HospitalException(StrUtil.format("{}实体类上面注解要有@TableId(value='数据库的列')注解", className));
        }



        brandNameDto.setTableName( tableNameValue );

        //商家字段信息
        if(shopColumnName!=null) {
            //brandNameDto.setShopId(AdminInfoUtil.getShopId());
            brandNameDto.setShopId(2L);
            brandNameDto.setShopColumnName(shopColumnName);
        }

        brandNameDto.setColumName(columnName);
        brandNameDto.setColumnValue( columnValue );


        int count = this.existsService.existsValue(brandNameDto);
        if(count>0){
            String msg= StrUtil.format(AckCode.DATA_EXISTS.getMsg(),  "该商家中,"+columnValue);
            throw new HospitalException(msg);
        }
    }

    /**
     * 验证管理员数据唯一的
     * @param entity   实体类(mybatis-plus声明过)
     * @param columnName       验证数据库某个列名
     * @param columnValue      验证数据库某个列的值
     */
    protected void adminValidateExistsValue(Object entity,String columnName,String columnValue) throws IllegalAccessException {
        this.shopValidateExistsValue(entity,null,columnName,columnValue);
    }

    //转变的依赖字符
    private static final char UNDERLINE='_';

    /**
     * 将驼峰转换成"_"(userId 换成 user_id)
     * @param param
     * @return
     */
    public static String camelToUnderline(String param){
        if (param==null||"".equals(param.trim())){
            return "";
        }
        int len=param.length();
        StringBuilder sb=new StringBuilder(len);
        for (int i = 0; i < len; i++) {
            char c=param.charAt(i);
            if (Character.isUpperCase(c)){
                sb.append(UNDERLINE);
                sb.append(Character.toLowerCase(c));
            }else{
                sb.append(c);
            }
        }
        return sb.toString();
    }

}



